package cn.lingyangwl.agile.msg.push.core.channel.client;

import cn.lingyangwl.agile.msg.push.api.constatnts.ChannelCodeEnum;
import cn.lingyangwl.agile.msg.push.core.channel.MsgChannel;
import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;

import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 消息渠道客户端包装器材
 * @author shenguangyang
 */
@Slf4j
public abstract class BaseMsgChannelClient {
    protected MsgChannel msgChannel;

    public static final Map<ChannelCodeEnum, Class<? extends BaseMsgChannelClient>> channelMap = new ConcurrentHashMap<>();

    public static void initMsgChannel() throws Exception {
        Reflections reflection = new Reflections(new ConfigurationBuilder()
                .setScanners(Scanners.SubTypes)
                .setUrls(ClasspathHelper.forPackage(BaseMsgChannelClient.class.getPackage().getName()))
                .filterInputsBy(new FilterBuilder()));
        Set<Class<? extends BaseMsgChannelClient>> subTypesOf = reflection.getSubTypesOf(BaseMsgChannelClient.class);
        for (Class<? extends BaseMsgChannelClient> subClass : subTypesOf) {
            try {
                boolean isAbstract = Modifier.isAbstract(subClass.getModifiers());
                if (isAbstract) {
                    continue;
                }

                BaseMsgChannelClient baseMsgChannelClient = subClass.getDeclaredConstructor(MsgChannel.class).newInstance(new MsgChannel());
                channelMap.put(baseMsgChannelClient.channelCode(), subClass);
            } catch (Exception e) {
                log.info("inti class {} fail", subClass.getName());
                throw e;
            }
        }
    }

    public abstract ChannelCodeEnum channelCode();

    public abstract void init();

    public BaseMsgChannelClient(MsgChannel msgChannel) {
        this.msgChannel = msgChannel;
    }

    public MsgChannel getMsgChannel() {
        return msgChannel;
    }

    public void setMsgChannel(MsgChannel msgChannel) {
        this.msgChannel = msgChannel;
    }
}
